<?php

namespace App\Http\Controllers\API;

use App\Http\Requests\API\CreateUserModelAPIRequest;
use App\Http\Requests\API\UpdateUserModelAPIRequest;
use App\Http\Services\UtilService;
use App\Models\AppConfigModel;
use App\Models\CityModel;
use App\Models\FacilityModel;
use App\Models\FacilityTicketModel;
use App\Models\TicketModel;
use App\Models\UserModel;
use App\Models\UserTicketModel;
use App\Repositories\TicketModelRepository;
use App\Repositories\UserTicketRepository;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use InfyOm\Generator\Criteria\LimitOffsetCriteria;
use Prettus\Repository\Criteria\RequestCriteria;
use App\Http\Services\TicketDTOBuilderService;
use Response;
use Validator;
use DB;


/**
 * 优惠券控制器
 * Class TicketController
 * @package App\Http\Controllers\API
 */
class TicketController extends AppBaseController
{
    /** @var  ticketModelRepository */
    private $ticketModelRepository;

//    public function __construct(ticketModelRepository $repository)
//    {
//        $this->ticketModelRepository = $repository;
//    }

    /**
     * @param TicketModelRepository $repo
     */
    public function search(TicketModelRepository $repo)
    {
        $input = $this->request->all();

        $searchOptions = $this->normalizeSearchOptions();
        $sortOptions = $this->normalizeSortOptions();
        $cityId = array_get($input, 'city_id', 0);
        !empty($cityId) && $searchOptions['city_id'] = $cityId;
        $cateogyId = array_get($input, 'category_id', 0);
        !empty($cateogyId) && $searchOptions['category_id'] = $cateogyId;
        $searchOptions['status'] = 0;

        $ret = $repo->search($searchOptions, $sortOptions);

        $lists = $ret['lists'];
        if (count($lists) == 0) {
            return $this->success(['lists' => []]);
        }

        $lists = TicketDTOBuilderService::buildTickets($this->request->attributes->get('user_id'), $lists);
        $ret['lists'] = $lists;

        return $this->success($ret);
    }

    /**
     * @param TicketModelRepository $repo
     */
    public function search2(TicketModelRepository $repo)
    {
        $input = $this->request->all();

        $searchOptions = $this->normalizeSearchOptions();
        $sortOptions = $this->normalizeSortOptions();
        $cityId = array_get($input, 'city_id', 0);
        $ticketType = array_get($input, 'ticket_type', null);
        isset($ticketType) && $searchOptions['ticket_type'] = $ticketType;
        !empty($cityId) && $searchOptions['city_id'] = $cityId;
        $cateogyId = array_get($input, 'category_id', 0);
        !empty($cateogyId) && $searchOptions['category_id'] = $cateogyId;
        $searchOptions['status'] = 0;

        $ret = $repo->search($searchOptions, $sortOptions);

        $lists = $ret['lists'];
        if (count($lists) == 0) {
            return $this->success(['lists' => []]);
        }

        $lists = TicketDTOBuilderService::buildTickets2($lists);
        $ret['lists'] = $lists;

        return $this->success($ret);
    }

    /**
     * 精选的优惠券
     * @param TicketModelRepository $repo
     * @return \Illuminate\Http\JsonResponse
     */
    public function searchHot(TicketModelRepository $repo)
    {
        $input = $this->request->all();

        $searchOptions = $this->normalizeSearchOptions();
        $sortOptions = $this->normalizeSortOptions();
        $cityId = array_get($input, 'city_id', 0);
        !empty($cityId) && $searchOptions['city_id'] = $cityId;
        $cateogyId = array_get($input, 'category_id', 0);
        !empty($cateogyId) && $searchOptions['category_id'] = $cateogyId;
        $searchOptions['status'] = 0;

        // 从配置中取出精选的代金券ID
        $value = AppConfigModel::findOneByKey(AppConfigModel::HOT_TICKET);
        if (!empty($value)) {
            $searchOptions['id'] = explode(',', $value);
        } else {
            return $this->success(['lists' => []]);
        }
        $ret = $repo->search($searchOptions, $sortOptions);

        $lists = $ret['lists'];
        if (count($lists) == 0) {
            return $this->success(['lists' => []]);
        }

        $lists = TicketDTOBuilderService::buildTickets($this->request->attributes->get('user_id'), $lists);
        $ret['lists'] = $lists;

        return $this->success($ret);
    }

    /**
     * 领券接口
     * @param TicketModelRepository $ticketRepo
     * @param UserTicketRepository $userTicketRepo
     */
    public function fetchTicket($id, TicketModelRepository $ticketRepo, UserTicketRepository $userTicketRepo)
    {
        // 验证用户是否有资格领取优惠券
        if (!$this->request->attributes->get('user')->is_active) {
            throwResponseException(1, '未注册不能领取');
        }

        $userId = $this->request->attributes->get('user_id');
        // 验证某个券是否可用
        $ticket = $ticketRepo->findWithoutFail($id);

        // 验证ticket 是否有效, 是否过期
        $ticketRepo->validateTicket($ticket);

        // 验证用户是否已经领取过优惠券
        $usetTickets = $userTicketRepo->findWhere(['ticket_id' => $ticket->id, 'user_id' => $userId]);
        if (count($usetTickets) >= $ticket->use_limit) {
            throwResponseException(1, '优惠券已领取');
        }

        // 事务操作
        $ret = runInTransaction(function () use ($userId, $ticket, $userTicketRepo) {
            // 更新ticket 数量
            $ret = DB::table('ticket')
                ->where('id', $ticket->id)
                ->where('left_times', '>=', 1)
                ->decrement('left_times', 1);
            if ($ret == 0) {
                throwResponseException(CODE_TICKET_OUT);
            }

            // 插入
            $attributes = [
                'user_id' => $userId,
                'ticket_id' => $ticket->id,
                'city_id' => $ticket->city_id,
                'category_id' => $ticket->category_id,
                'code' => UtilService::convert36(time() . mt_rand(100, 999)),
            ];
            return $userTicketRepo->create($attributes);
        });

        return $this->success($ret->toArray());
    }

    /**
     * Store a newly created UserModel in storage.
     * POST /userModels
     *
     * @param CreateUserModelAPIRequest $request
     *
     * @return Response
     */
    public function store(TicketModelRepository $ticketModelRepository)
    {
        $input = $this->request->all();
        $this->validateInputParams('store', $input);
        $cityId = $input['city_id'];
        $city = CityModel::where('id', $cityId)->first();
        if (empty($city)) {
            return $this->error(1, '城市ID非法');
        }

        if (isset($input['type']) &&  $input['type'] == 1 && !isset($input['valid_time'])) {
            return $this->error("限时优惠券需要上传时间");
        } elseif (isset($input['type']) &&  $input['type'] == 1 && strtotime($input['valid_time']) < time()) {
            return $this->error(1, "限时优惠券时间大于当前时间");
        } elseif ($input['type'] == 0) {
            unset($input['valid_time']);
        }

        $input['city_name'] = $city->city;
        $input['left_times'] = $input['max_times'];
        $userModels = $ticketModelRepository->create($input);

        return $this->sendResponse($userModels->toArray(), '新增优惠券成功');
    }

    /**
     * @param $id
     * @param TicketModelRepository $ticketModelRepository
     * @return \Illuminate\Http\JsonResponse
     */
    public function show($id, TicketModelRepository $ticketModelRepository, UserTicketRepository $userTicketRepository)
    {
        /** @var UserModel $userModel */
        $ticketModel = $ticketModelRepository->findWithoutFail($id);

        if (empty($ticketModel)) {
            return $this->sendError('优惠券不存在');
        }

        $ret = $ticketModel->toArray();
        $arr = $userTicketRepository->getUserTicket($this->request->attributes->get('user_id'), $ticketModel->id);
        if (empty($arr)) {
            $cnt = 0;
            $ret = TicketDTOBuilderService::buildTicket($this->request->attributes->get('user_id'), $ret, $cnt);
        } else {
            $cnt = count($arr);
            $map = arrToMap($arr, 'ticket_id', true);
            $ret = TicketDTOBuilderService::buildTicket($this->request->attributes->get('user_id'), $ret, $cnt, $map);

        }

        return $this->sendResponse($ret, 'User Model retrieved successfully');
    }

    /**
     * Update the specified UserModel in storage.
     * PUT/PATCH /userModels/{id}
     *
     * @param  int $id
     * @param UpdateUserModelAPIRequest $request
     *
     * @return Response
     */
    public function update($id, TicketModelRepository $ticketModelRepository)
    {
        $input = $this->request->all();

        $this->validateInputParams('update', $input);
        $cityId = $input['city_id'] ?? 0;

        if ($cityId) {
            $city = CityModel::where('id', $cityId)->first();
            if (empty($city)) {
                return $this->error(1, '城市ID非法');
            }

            $input['city_name'] = $city->city;
        }

        if (isset($input['type']) &&  $input['type'] == 1 && !isset($input['valid_time'])) {
            return $this->error("限时优惠券需要上传时间");
        } elseif (isset($input['type']) &&  $input['type'] == 1 && strtotime($input['valid_time']) < time()) {
            return $this->error(1, "限时优惠券时间大于当前时间");
        }

        /** @var UserModel $userModel */
        $model = $ticketModelRepository->findWithoutFail($id);

        if (empty($model)) {
            return $this->sendError('优惠券不存在');
        }

        if (isset($input['max_times']) && isset($input['left_times'])) {
            if ($input['max_times'] < $input['left_times']) {
                return $this->error(1, '剩余次数必须小于总可使用次数');
            }
        } elseif (isset($input['max_times']) && !isset($input['left_times'])) {
            if ($model->left_times > $input['max_times']) {
                return $this->error(1, '剩余次数必须小于总可使用次数');
            }
        } elseif (!isset($input['max_times']) && isset($input['left_times'])) {
            if ($model->max_times < $input['left_times']) {
                return $this->error(1, '剩余次数必须小于总可使用次数');
            }
        }

        $model->updateRecord($id, $input);

        return $this->sendResponse([], '操作成功');
    }

    /**
     * Update the specified UserModel in storage.
     * PUT/PATCH /userModels/{id}
     *
     * @param  int $id
     * @param UpdateUserModelAPIRequest $request
     *
     * @return Response
     */
    public function setHot()
    {
        $input = $this->request->all();

        $ticketId = $input['ticket_ids'];
        if (empty($ticketId)) {
            return $this->sendError("优惠券不存在");
        }

        $flag = $this->request->input('flag', 1);
        if (empty($ticketId)) {
            return $this->sendError("优惠券不存在");
        }

        $ticketList = TicketModel::whereIn('id', explode(',', $ticketId))->where('status', 0)->get()->toArray();
        if (empty($ticketList)) {
            return $this->sendError("优惠券不存在");
        }

        $idList = array_column($ticketList, 'id');
        $ids = implode(',', $idList);

        $model = AppConfigModel::where('key', AppConfigModel::HOT_TICKET)->first();
        $v = $model->value;
        // 加精
        if ($flag) {
            if (!empty($v)) {
                $vList = explode(',', $v);
                $newArr = array_unique(array_merge($vList, $idList));
                $model->value = implode(',', $newArr);
            } else {
                $model->value = $ids;
            }
        // 取消
        } else {
            if (!empty($v)) {
                $vList = explode(',', $v);
                $joinList = array_intersect($idList, $vList);
                $newArr = array_diff($vList, $joinList);

                !empty($newArr) && $model->value = implode(',', $newArr);
            } else {
                $model->value = '';
            }
        }

        $model->save();

        return $this->sendResponse([], '操作成功');
    }

    /**
     * Update the specified UserModel in storage.
     * PUT/PATCH /userModels/{id}
     *
     * @param  int $id
     * @param UpdateUserModelAPIRequest $request
     *
     * @return Response
     */
    public function setKeywords()
    {
        $input = $this->request->all();

        $name = $input['name'];
        if (empty($name)) {
            return $this->sendError("推荐词不存在");
        }

        AppConfigModel::updateOneByKey(AppConfigModel::KEYWORDS, $name);

        return $this->sendResponse([], '操作成功');
    }

    /**
     * Remove the specified AdminModel from storage.
     * DELETE /adminModels/{id}
     *
     * @param  int $idbatch
     *
     */
    public function batchDestroy()
    {
        $ids = $this->request->get('ticket_ids');
        if (empty($ids)) {
            return $this->sendError('id不为空');
        }

        $ids = explode(',', $ids);
        // 删除ticket
        TicketModel::whereIn('id', $ids)->update(['status' => 2]);
        // 解除绑定
        FacilityTicketModel::whereIn('ticket_id', $ids)->delete();
        // 删除用户的代金券
        UserTicketModel::whereIn('ticket_id', $ids)->delete();

        return $this->success([], '操作成功');
    }

    /**
     * Remove the specified UserModel from storage.
     * DELETE /userModels/{id}
     * @param  facility_ids
     * @param  int $id
     *
     * @return Response
     */
    public function bindFacility($id, TicketModelRepository $ticketModelRepository)
    {
        $ticketModel = $ticketModelRepository->findWithoutFail($id);
        if (empty($ticketModel) || $ticketModel->status == 2) {
            return $this->sendError('优惠券不存在或已删除');
        }

        $fids = $this->request->get('facility_ids');
        if (empty($fids)) {
            return $this->sendError('酒店商业等ID不为空');
        }

        $fids = explode(',', $fids);

        $facilityList = FacilityModel::select('name')->whereIn('id', $fids)->get()->toArray();

        if (!empty($facilityList)) {
            $name = array_column($facilityList, 'name');
            $keywords = implode(' ', $name);
            $ticketModel->keywords = $keywords;
            $ticketModel->save();
        } else {
            return $this->error(1, '酒店商业不存在');
        }

        // 先删除老的,再出入新的
        FacilityTicketModel::where('ticket_id', $id)->delete();
        $this->batchInsert($id, $fids);

        return $this->sendResponse([], '操作成功');
    }

    private function batchInsert($ticketId, $fids)
    {
        foreach ($fids as $fid) {
            $data[] = ['facility_id' => $fid, 'ticket_id' => $ticketId];
        }

        DB::table('facility_ticket')->insert($data);
    }

    /**
     * 参数验证规则
     * self::VALID_RULES[__FUNCTION__]
     */
    const VALID_RULES = [
        'store' => [
            'category_id' => 'required|int|min:10|max:12',
            'city_id' => 'required|int',
            'use_limit' => 'int|min:1',
            'type' => 'required|int|min:0|max:1',
            'start_time' => 'required|date',
            'end_time' => 'required|date',
            'valid_time' => 'nullable|date',
            'max_times' => 'required|int|min:1',
            'ticket_type' => 'required|int|min:0|max:2',
            'use_condition' => 'required|string',
            'payment' => 'required|string',
            'bargin_condition' => 'required|string',
            'name' => 'required|string',
            'keywords' => 'string',
        ],
        'update' => [
            'category_id' => 'int|min:10|max:12',
            'city_id' => 'int',
            'use_limit' => 'int|min:1',
            'type' => 'int|min:0|max:1',
            'start_time' => 'nullable|date',
            'end_time' => 'nullable|date',
            'valid_time' => 'nullable|date',
            'max_times' => 'int|min:1',
            'ticket_type' => 'int|min:0|max:2',
            'use_condition' => 'string',
            'keywords' => 'string',
            'use_condition' => 'string',
            'payment' => 'string',
            'bargin_condition' => 'string',
            'name' => 'string',
        ],
    ];
}
